package com.hanshg.cherry.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hanshg.cherry.base.core.Constants;
import com.hanshg.cherry.base.result.Results;
import com.hanshg.cherry.config.aliyun.SmsConfig;
import com.hanshg.cherry.dto.LoginUser;
import com.hanshg.cherry.dto.UserDto;
import com.hanshg.cherry.mapper.RoleUserMapper;
import com.hanshg.cherry.mapper.UserMapper;
import com.hanshg.cherry.model.SysRoleUser;
import com.hanshg.cherry.model.SysUser;
import com.hanshg.cherry.service.UserService;
import com.hanshg.cherry.util.StringUtils;
import com.hanshg.cherry.util.aliyun.SmsUtil;
import com.hanshg.cherry.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * @author 柠檬水
 */
@Service
@Transactional
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SmsUtil smsUtil;

    @Autowired
    private SmsConfig smsConfig;

    @Override
    public SysUser getUser(String username) {
        return userMapper.getUser(username);
    }

    @Override
    public SysUser getUserById(Long id) {
        return userMapper.getUserById(id);
    }

    @Override
    public int deleteUser(Long id) {
        roleUserMapper.deleteRoleUserByUserId(id);

        return userMapper.deleteUser(id);
    }

    @Override
    public int saveUser(SysUser sysUser) {
        return userMapper.saveUser(sysUser);
    }

    @Override
    public int updateUser(SysUser sysUser) {
        return userMapper.updateUser(sysUser);
    }

    @Override
    public Results<SysUser> getAllUserByPage(Integer offset, Integer limit) {
        return Results.success(userMapper.countUser(), userMapper.getAllUserByPage(offset, limit));
    }

    @Override
    public Results<SysUser> save(SysUser sysUser, Long roleId) {
        if (roleId != null) {
            //保存用户
            userMapper.saveUser(sysUser);

            //保存角色
            SysRoleUser sysRoleUser = new SysRoleUser();
            sysRoleUser.setRoleId(roleId);
            sysRoleUser.setUserId(sysUser.getId());
            roleUserMapper.save(sysRoleUser);
            return Results.success();
        }
        return Results.failure();
    }

    @Override
    public SysUser getUserByPhone(String phone) {
        return userMapper.getUserByPhone(phone);
    }

    @Override
    public SysUser getUserByUserName(String username) {
        return userMapper.getUser(username);
    }

    @Override
    public SysUser getUserByEmail(String email) {
        return userMapper.getUserByEmail(email);
    }

    @Override
    public Results<SysUser> updateUser(UserDto userDto, Long roleId) {
        if (roleId != null) {
            userDto.setUpdateTime(new Date());
            userMapper.updateUser(userDto);

            SysRoleUser sysRoleUser = new SysRoleUser();
            sysRoleUser.setRoleId(roleId);
            sysRoleUser.setUserId(userDto.getId());
            if (roleUserMapper.getSysRoleUserByUserId(userDto.getId()) != null) {
                roleUserMapper.updateSysRoleUser(sysRoleUser);
            } else {
                roleUserMapper.save(sysRoleUser);
            }
            return Results.success();
        }
        return Results.failure();
    }

    @Override
    public Results<SysUser> findUserByUsername(String username, Integer offset, Integer limit) {
        return Results.success(userMapper.findUserByUsername(username), userMapper.findUserByUsernameByPage(username, offset, limit));
    }

    @Override
    public Results<SysUser> changePassword(String username, String oldPassword, String newPassword) {
        SysUser u = userMapper.getUser(username);
        if (u == null) {
            return Results.failure(1, "用户不存在");
        }
        if (!new BCryptPasswordEncoder().matches(oldPassword, u.getPassword())) {
            return Results.failure(1, "原密码错误");
        }
        userMapper.changePassword(u.getId(), new BCryptPasswordEncoder().encode(newPassword.trim()));
        return Results.success();
    }

    /**
     * 获取登录用户
     *
     * @return {@link LoginUser}
     */
    @Override
    public LoginUser getLoginUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        return loginUser;
    }

    /**
     * 发送短信
     *
     * @param mobile
     */
    @Override
    public JSONObject sendSms(String mobile) {
        //实现发送信息
        JSONObject json = new JSONObject();
        //验证是否开启验证码发送功能
        if (smsConfig.getFlag().equals(Constants.IS_FLAG_FALSE)) {
            json.put("Code", "NO");
            json.put("Message", "系统已禁止发送短信，请在配置文件中开启");
            return json;
        }
        if (StringUtils.isEmpty(mobile)) {
            json.put("Code", "NO");
            json.put("Message", "参数输入错误，请重新输入");
            return json;
        }
        //设置发送次数
        long count = redisUtil.incr(Constants.REDIS_SMS_USER_PREFIX + mobile, 1);
        log.info(Constants.REDIS_SMS_USER_PREFIX + mobile + "发送次数：" + redisUtil.get(Constants.REDIS_SMS_USER_PREFIX + mobile));
        //验证发送次数
        if (count > 5) {
            //超过5次设置为24小时超时时间
            redisUtil.expire(Constants.REDIS_SMS_USER_PREFIX + mobile, Constants.REDIS_SMS_USER_EXPIRE);
            json.put("Code", "NO");
            json.put("Message", "验证码发送频繁,请24小时后在重试");
            return json;
        }

        //生成6位数验证码
        String checkCode = RandomStringUtils.randomNumeric(Constants.SMS_LENGTH);
        log.info("短信验证码已生成：" + checkCode);

        //验证码存入缓存,为了注册的时候校验验证码是否正确 有效期5分钟
        redisUtil.set(Constants.CHECK_CODE + mobile, checkCode, Constants.REDIS_SMS_EXPIRE);
        log.info("短信验证码：" + checkCode + ",已加入缓存有效期5分钟");
        String sendSms = smsUtil.sendSms(mobile, "{\"code\":\"" + checkCode + "\"}");
        if (!StringUtils.isEmpty(sendSms)) {
            return JSON.parseObject(sendSms);
        } else {
            json.put("Code", "NO");
            json.put("Message", "发送失败");
        }
        return json;
    }
}